# coding=utf-8
import tornado.web

import WrapCursor
from CommonLib import *
from database.models.Controller import Controller
from database.models.ControllerPoint import ControllerPoint
from database.models.DatabaseCommon import *
from database.models.OptType import OptType


class SetSinglePoint(tornado.web.RequestHandler):
    __metaclass__ = ABCMeta

    def SendToBoard(self, controllerID, curentValue, pointIndex, opt, hard_id, board_mark):
        sendWrap = SendWrap(device_listen_addr)
        session = Session()
        controller = session.query(Controller).with_for_update(read=False, nowait=False).filter_by(
            id=controllerID).one()
        if curentValue == "\"\"" or curentValue == '':
            curentValue = "0"
        cl = int(curentValue) & 0xff
        ch = int(curentValue) & 0xff00
        ch = ch >> 8

        # 通过point index 组装 发送数据
        l = 0
        h = 0
        oneN = 1

        if int(pointIndex) > 8:
            h = oneN << (int(pointIndex) - 8 - 1)
        else:
            l = oneN << int(pointIndex - 1)

        # 通过opt组合发送的数据
        if opt is 1:
            l = l | cl
            h = h | ch
        if opt is 2:
            h = ~h & ch
            l = ~l & cl
        # 写会数据库下次使用
        curentValue = (h << 8 | l) & 0xffff
        controller.Value = str(curentValue)
        session.commit()
        # time.sleep(0.2)
        send2board = [0] * 10
        send2board[1] = (hard_id >> 8) & 0xff
        send2board[0] = (hard_id >> 0) & 0xff
        send2board[2] = l
        send2board[3] = h
        send2board[4] = 0  # board_mark >> 8 & 0xff
        send2board[5] = 0  # board_mark >> 8 * 0 & 0xff
        send2board[6] = 0  # (hard_id >> 8) & 0xff
        send2board[7] = 0  # (hard_id >> 0) & 0xff
        send2board[8] = 0
        send2board[9] = 0
        intret = 0
        if global_status.ai_ele_global_status.config['with-hardwork']:
            intret = sendWrap.SendData(send2board)
        return intret

    def post(self):
        bodycontext = self.request.body
        ojson = None
        r = WrapCursor.WrapCursor()
        controllerID = None
        pointIndex = None
        opt = None

        try:
            ojson = json.loads(self.request.body)
            controllerID = ojson['ControllerID']
            pointIndex = ojson['PointIndex']
            opt = ojson['Opt']
            CheckJsonKeys(ojson, 'username', 'userpass')
            CheckAuth(ojson)
        except Exception as e:
            self.write(r.Error('request data error :' + str(e)))
            return

        session = Session()
        if session.query(OptType).filter_by(id=opt).count() is not 1:
            self.write(r.Error('request opt error'))
            return
        controller = session.query(Controller).filter_by(id=controllerID).all()
        if len(controller) is not 1:
            self.write(r.Error('request Controller error'))
            return
        controllerPoint = session.query(ControllerPoint).filter_by(ControllerID=controllerID,
                                                                   PointIndex=pointIndex).all()
        if len(controllerPoint) != 1:
            self.write(r.Error('request controller_manager point index error'))
            return
        if global_status.ai_ele_global_status.config['with-hardwork']:
            intret = self.SendToBoard(controllerID=controllerID, curentValue=int(controller[0].Value),
                                      pointIndex=pointIndex, opt=opt, hard_id=controller[0].HardID,
                                      board_mark=int(controller[0].tag))
            if intret is None or intret.ok is False:
                self.write(r.Error("master board not online"))
                return
            intret = json.loads(intret.text)
            if intret['code'] is 0:
                self.write(r.Ok('single point opt ok'))
            else:
                self.write(r.Error('Send Driver Fail'))
            return
        else:
            self.write(r.Ok('single point opt ok'))
            return
